/*
 PureMVC - Copyright(c) 2006-08 Futurescale, Inc., Some rights reserved.
 Your reuse is governed by the Creative Commons Attribution 3.0 United States License
*/
package org.puremvc.as3.patterns.observer
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	import mx.binding.utils.ChangeWatcher;
	
	import org.puremvc.as3.events.MvcCreateCompleteEvent;
	import org.puremvc.as3.interfaces.*;
	import org.puremvc.as3.patterns.facade.Facade;
	import org.puremvc.as3.patterns.mediator.Mediator;
	
	/**
	 * A Base <code>INotifier</code> implementation.
	 * 
	 * <P>
	 * <code>MacroCommand, Command, Mediator</code> and <code>Proxy</code> 
	 * all have a need to send <code>Notifications</code>. <P>
	 * <P>
	 * The <code>INotifier</code> interface provides a common method called
	 * <code>sendNotification</code> that relieves implementation code of 
	 * the necessity to actually construct <code>Notifications</code>.</P>
	 * 
	 * <P>
	 * The <code>Notifier</code> class, which all of the above mentioned classes
	 * extend, provides an initialized reference to the <code>Facade</code>
	 * Singleton, which is required for the convienience method
	 * for sending <code>Notifications</code>, but also eases implementation as these
	 * classes have frequent <code>Facade</code> interactions and usually require
	 * access to the facade anyway.</P>
	 * 
	 * @see org.puremvc.as3.patterns.facade.Facade Facade
	 * @see org.puremvc.as3.patterns.mediator.Mediator Mediator
	 * @see org.puremvc.as3.patterns.proxy.Proxy Proxy
	 * @see org.puremvc.as3.patterns.command.SimpleCommand SimpleCommand
	 * @see org.puremvc.as3.patterns.command.MacroCommand MacroCommand
	 */
	public class Notifier extends EventDispatcher implements INotifier 
	{
		public function Notifier()
		{
			super();
			
			facade.addEventListener(MvcCreateCompleteEvent.MVC_CREATE_COMPLETE_EVENT,mvcCreateCompleteHandler,false,0,true);
		}
		
		/**
		 * Create and send an <code>INotification</code>.
		 * 
		 * <P>
		 * Keeps us from having to construct new INotification 
		 * instances in our implementation code.
		 * @param notificationName the name of the notiification to send
		 * @param body the body of the notification (optional)
		 * @param type the type of the notification (optional)
		 */ 
		public function sendNotification( notificationName:String, body:Object=null, type:String=null ):void 
		{
			facade.sendNotification( notificationName, body, type );
		}
		
		// Local reference to the Facade Singleton
		protected var facade:IFacade = Facade.getInstance();
		
		public function getProxy(proxyClass:Class):*
		{
			return facade.retrieveProxy(proxyClass.NAME) as proxyClass;
		}
		
		public function getMediator(proxyClass:Class,callBack:Function=null):*
		{
			var medName:String=proxyClass.NAME;
			var med:Mediator= facade.retrieveMediator(medName) as Mediator;
			
			if(callBack!=null)
			{
				if(med==null && callBack!=null)
				{
					var funcList:Array=_createMedCallBackFuncDIC[medName];
					if(funcList==null)
						funcList=_createMedCallBackFuncDIC[medName]=[];
					
					funcList.push(callBack);
				}
				else
					callBack(med);
			}	
			return med;
		}
		
		private function mvcCreateCompleteHandler(event:MvcCreateCompleteEvent):void
		{
			var funcList:Array=_createMedCallBackFuncDIC[event.mvcName];
			var fun:Function;
			if(funcList)
			{
				for (var i:int = 0; i < funcList.length; i++) 
				{
					fun=funcList[i];
					fun(event.med);
				}
				
				delete _createMedCallBackFuncDIC[event.mvcName];
			}
		}
		
		private var _createMedCallBackFuncDIC:Object={};
		
		private var _cwList:Vector.<ChangeWatcher>;
		
		public function removeCWList():void
		{
			if(_cwList)
			{
				while(_cwList.length>0)
				{
					_cwList.pop().unwatch();
				}
				
				_cwList=null;
				
			}
		}

		public function get cwList():Vector.<ChangeWatcher>
		{
			if(!_cwList)
				_cwList=new Vector.<ChangeWatcher>();
			
			return _cwList;
		}
	}
}